package com.symaster.gameengine.test;

import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL32;

public class FBORenderCircle {
    private long window;
    private int fbo;       // FBO ID
    private int texture;   // Texture ID

    public void run() {
        init();
        setupFBO();
        loop();

        // 清理资源
        GLFW.glfwDestroyWindow(window);
        GLFW.glfwTerminate();
    }

    private void init() {
        if (!GLFW.glfwInit()) {
            throw new IllegalStateException("Unable to initialize GLFW");
        }

        window = GLFW.glfwCreateWindow(800, 600, "FBO Red Circle", 0, 0);
        if (window == 0) {
            throw new RuntimeException("Failed to create the GLFW window");
        }

        GLFW.glfwMakeContextCurrent(window);
        GL.createCapabilities();

        GL11.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);  // 背景色黑色
    }

    private void setupFBO() {
        // 创建FBO
        fbo = GL30.glGenFramebuffers();
        GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, fbo);

        // 创建纹理并作为颜色附件
        texture = GL11.glGenTextures();
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
        GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 800, 600, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (java.nio.ByteBuffer) null);

        // 设置纹理参数
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);

        // 绑定纹理作为FBO的颜色附件
        GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, texture, 0);

        // 创建渲染缓冲区作为深度附件
        int rbo = GL30.glGenRenderbuffers();
        GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, rbo);
        GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_DEPTH24_STENCIL8, 800, 600);
        GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_STENCIL_ATTACHMENT, GL30.GL_RENDERBUFFER, rbo);

        // 检查 FBO 是否完整
        if (GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER) != GL30.GL_FRAMEBUFFER_COMPLETE) {
            throw new RuntimeException("FBO is not complete!");
        }

        // 解绑FBO，回到默认帧缓冲区
        GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
    }

    private void loop() {
        while (!GLFW.glfwWindowShouldClose(window)) {
            // 渲染到 FBO
            GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, fbo);
            GL11.glViewport(0, 0, 800, 600); // 设置视口大小

            // 清除FBO中的内容
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            drawRedCircle();  // 在FBO中绘制红色的圆

            // 渲染到窗口（默认帧缓冲区）
            GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
            GL11.glViewport(0, 0, 800, 600); // 设置视口为窗口大小

            // 清除窗口中的内容
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            renderTextureToScreen();  // 将FBO中的内容渲染到窗口

            GLFW.glfwSwapBuffers(window);
            GLFW.glfwPollEvents();
        }
    }

    private void drawRedCircle() {
        GL11.glColor3f(1.0f, 0.0f, 0.0f); // 设置颜色为红色
        GL11.glBegin(GL11.GL_TRIANGLE_FAN);
        GL11.glVertex2f(0.0f, 0.0f); // 中心点

        int numSegments = 100;
        float radius = 0.5f;
        for (int i = 0; i <= numSegments; i++) {
            double theta = 2.0 * Math.PI * i / numSegments;
            float x = (float) (radius * Math.cos(theta));
            float y = (float) (radius * Math.sin(theta));
            GL11.glVertex2f(x, y);
        }
        GL11.glEnd();
    }

    private void renderTextureToScreen() {
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
        GL11.glEnable(GL11.GL_TEXTURE_2D);

        GL11.glBegin(GL11.GL_QUADS);
        GL11.glTexCoord2f(0.0f, 0.0f);
        GL11.glVertex2f(-1.0f, -1.0f);

        GL11.glTexCoord2f(1.0f, 0.0f);
        GL11.glVertex2f(1.0f, -1.0f);

        GL11.glTexCoord2f(1.0f, 1.0f);
        GL11.glVertex2f(1.0f, 1.0f);

        GL11.glTexCoord2f(0.0f, 1.0f);
        GL11.glVertex2f(-1.0f, 1.0f);
        GL11.glEnd();

        GL11.glDisable(GL11.GL_TEXTURE_2D);
    }

    public static void main(String[] args) {
        new FBORenderCircle().run();
    }
}
